import { uniqueArray, minus } from '@/utils/calc'

var optimize = function optimize(data) {

    var self = this;
    // self.parent = model;
    self.submitAction = "";
    self.data = data;
    self.peifulv = 1;
    self.isDanchang = false;

    // if (self.data.lottery == "danchang") {
    //     $.lottery.danchangConfig(); //--北单配置初始化
    //     self.peifulv = 0.65;
    //     self.isDanchang = true;
    // }

    /**
     * 由于接口的需求，提交的数据中count和money需要使用原始的count和money，优化后的数量存在count_optimize中
     * 但现在的代码中，count和money已经直接参与计算，直接改动牵扯太广
     * 因此数据逻辑如此设计：
     * 使用self.oldData对象来存储原始的count和money，数据中的count和money功能不变，继续参与计算，
     * 再提交数据之前，将计算后的count存入count_optimize，然后将count和money更新到原始数据
     */
    self.listInfo = {
        //--列表描述信息，投注花费 和 中奖最大值、最小值
        money: 0,
        max: 0,
        min: 0
    };
    self.items = []; //--格式化后的组合数据
    self.guoguan = {}; //--不同过关方式对应数据，数据形式：{"1":[item,item…………],"2":[item,item…………]}
    self.ggMaps = self.data.guoguan.map(function (v) {
        //--过关方式数字映射，2_1映射为2，3_1映射为3，以此类推
        return v.replace("_1", "") * 1;
    });
    self.ggMaps.sort(); //--过关映射排序
    self.minMoney = self.data.money;
    var zuhe = self.data.zuhe;
    for (var i = 0, len = zuhe.length; i < len; i++) {
        var item = self.formatItem(zuhe[i]); //--组合数据格式化
        self.items.push(item);
    }
    self.moneys = []; //--所有总奖金集合，用于计算奖金最大值最小值
    self.maxMoneys = [];
    self.ms = []; //--所有单注奖金集合，用于总注数找平
    self.mMaps = {}; //--单注奖金映射，用于总注数找平，奖金会被格式化为整数
    self.zhushu = []; //--所有注数集合，用于计算总注数
    self.list = []; //--投注数据列表
    // self.listInfo = {};
    self.listOrder = []; //--投注数据列表，排序后
    var info = {};
    info.chang = self.data.changshu;
    info.guoguan = self.data.guoguan.join(",").replace(/_/g, "串");
    info.money = self.data.money;
    self.canHot = self.data.canHot; //--是否符合博冷波热的部分条件
    // self.parent.canHot = self.data.canHot;//--是否可以博冷博热
};
optimize.prototype.init = function (data) {
    var self = this;
    self.submitAction = "";
    self.data = data;
    self.peifulv = 1;
    self.isDanchang = false;
    self.listInfo = {
        //--列表描述信息，投注花费 和 中奖最大值、最小值
        money: 0,
        max: 0,
        min: 0
    };
    self.items = []; //--格式化后的组合数据
    self.guoguan = {}; //--不同过关方式对应数据，数据形式：{"1":[item,item…………],"2":[item,item…………]}
    self.ggMaps = self.data.guoguan.map(function (v) {
        //--过关方式数字映射，2_1映射为2，3_1映射为3，以此类推
        return v.replace("_1", "") * 1;
    });
    self.ggMaps.sort(); //--过关映射排序
    self.minMoney = self.data.money;
    var zuhe = self.data.zuhe;
    for (var i = 0, len = zuhe.length; i < len; i++) {
        var item = self.formatItem(zuhe[i]); //--组合数据格式化
        self.items.push(item);
    }
    self.moneys = []; //--所有总奖金集合，用于计算奖金最大值最小值
    self.maxMoneys = [];
    self.ms = []; //--所有单注奖金集合，用于总注数找平
    self.mMaps = {}; //--单注奖金映射，用于总注数找平，奖金会被格式化为整数
    self.zhushu = []; //--所有注数集合，用于计算总注数
    self.list = []; //--投注数据列表
    self.listOrder = []; //--投注数据列表，排序后
    var info = {};
    info.chang = self.data.changshu;
    info.guoguan = self.data.guoguan.join(",").replace(/_/g, "串");
    info.money = self.data.money;
    self.canHot = self.data.canHot; //--是否符合博冷波热的部分条件
};
optimize.prototype.formatItem = function (item) {
    //--格式化缓存数据，计算各自概率、单注奖金
    var self = this,
        r = {};
    r.guoguan = item.length + "串1"; //--过关
    r.text = []; //--赛事组合
    r.gailv = 1; //--概率
    r.money = 2; //--单注奖金
    for (var i = 0, len = item.length; i < len; i++) {
        var saishi = item[i],
            text = [saishi[0], saishi[3], saishi[6], saishi[5], saishi[2], saishi[1], saishi[7], saishi[8], saishi[9]],
            //--主队名、选择项、no、玩法
            peilv = saishi[4],
            //--赔率
            pankou = saishi[1],
            //--盘口
            peifulv = saishi[2]; //--赔付率
        if (peilv < 0) {
            text.push(pankou);
        } //--让球胜平负盘口
        r.text.push(text);
        peilv = Math.abs(peilv); //console.log(peilv, peifulv);
        r.money = r.money * peilv; //--计算单注奖金
        r.gailv = r.gailv * (1 / peilv * peifulv); //--计算组合概率
    }
    r.money = r.money * self.peifulv;
    if (self.isDanchang) {
        if (r.money > 500 * Math.pow(10, 4)) {
            r.money = 500 * Math.pow(10, 4);
        }
    }
    return r;
};
optimize.prototype.doAvg = function () {
    //--进行平均优化
    var self = this,
        items = self.items,
        allMoney = self.data.money,
        //--总金额
        zhushu = allMoney / 2,
        //--总注数
        x = 0;
    self.list = [];
    for (var i = 0, len = items.length; i < len; i++) {
        var item = items[i],
            o = {
                index: null,
                guoguan: item.guoguan,
                //--过关
                text: item.text,
                //--组合
                zhushu: null,
                //--注数
                money: null,
                //--奖金
                m: item.money,
                //--单注奖金
                hot: 0 //--博冷博热排序用，默认0，博冷博热项为1
            };
        x += 1 / o.m;
        self.list.push(o);
    }
    var sMoney = zhushu / x; //--平均单注奖金金额
    // console.log('平均单注奖金金额', sMoney)
    self.list.forEach(function (v, i) {
        var _zhushu = Math.floor(sMoney / v.m);
        v.zhushu = _zhushu == 0 ? 1 : _zhushu;
        v.money = v.m * v.zhushu;
        v.index = i;
        self.moneys.push(v.money); //--各总奖金集合
        // const notJoin = v.text.some(item => item[5] === false);
        // self.maxMoneys.push(notJoin ? 0 : v.money);
        var m = (v.m * 1).toFixed(2);
        self.ms.push(m); //--单注奖金集合
        self.ms = uniqueArray(self.ms);
        // self.ms = self.ms.uniquelize(); //--数组元素唯一化
        if (!self.mMaps[m]) {
            //--创造映射
            self.mMaps[m] = [v];
        } else {
            self.mMaps[m].push(v);
        }
        self.zhushu.push(v.zhushu); //--注数集合
        var len = v.text.length;
        if (!self.guoguan[len]) {
            self.guoguan[len] = [];
        }
        self.guoguan[len].push(v); //--引用到对应过关中
    });
    self.dataTongbu();
    self.doZhushuXiuzheng(); //--注数找平

    // if (self.parent.currAct == "avg") {
    self.doOrder("avg");
    // }
    // console.log(77777, self.listOrder);
};
optimize.prototype.dataTongbu = function () {
    //--集合以及映射数据修正
    var self = this;
    self.moneys = [];
    self.maxMoneys = [];
    self.ms = [];
    self.zhushu = [];
    self.mMaps = {};
    self.list.forEach(function (v) {
        v.money = v.m * v.zhushu;
        self.moneys.push(v.money); //--各总奖金集合
        // const notJoin = v.text.some(item => item[5] === false);
        // self.maxMoneys.push(notJoin ? 0 : v.money);
        var m = (v.m * 1).toFixed(2);
        self.ms.push(m); //--单注奖金集合
        self.ms = uniqueArray(self.ms);
        // self.ms = self.ms.uniquelize(); //--数组元素唯一化
        if (!self.mMaps[m]) {
            //--创造映射
            self.mMaps[m] = [v];
        } else {
            self.mMaps[m].push(v);
        }
        self.zhushu.push(v.zhushu); //--注数集合
    });
    // console.log(7777, self.ms, self.mMaps, self.zhushu);
};
function getNewListByNum(nArr = [], oArr = [], num) {
    const diffValArr = [], possibleObj = [];
    for (const item of nArr) {
        const newZs = item.zhushu + num; // 尝试增加或者减少注数 1 或者 -1;
        const otherArr = nArr.filter(comp => comp.index !== item.index);
        const first = { ...item, money: item.m * newZs, zhushu: newZs };
        const arr = [first, ...otherArr, ...oArr];
        // 计算是否平均（根据最大值和最小值的差来反映数据是否平均）
        const sortArr = arr.sort((a, b) => a.money - b.money);
        const min = sortArr[0].money, max = sortArr[sortArr.length - 1].money;
        // diffVal越小说明当前分配越平均
        const diffVal = max - min;
        diffValArr.push(diffVal);
        possibleObj[diffVal] = sortArr;
    }
    const minDiff = diffValArr.slice().sort((a, b) => a - b)[0];
    return possibleObj[minDiff];
}
optimize.prototype.doZhushuXiuzheng = function () {
    //--执行注数修正，当平均优化后注数与原注数不一致时，将其修正到一样；
    /**
     * 平均算法优化：
     * 1、使用N元一次方程解出每个赔率组合对应的注数，有小数向下取整，但小于1的情况置为1。
     * 2、当处理注数不等于设定注，则从低赔到高赔循环增减注数至设定注，但当前注为1的时候不在操作。
     * 例如
     * 赔率从小到大注数为：3、3、2、1、1、1，多3注，则为2、2、1、1、1、1
     * 赔率从小到大注数为：3、3、2、1、1、1，少2注，则为4、4、2、1、1、1
     * 3、进一步优化规则：判断是否有低于本金的奖金组合，如果有则从最低奖金组合减少1注至目标奖金组合，循环直至目标奖金赔率组合高于本金，但如果最低奖金组合减1小于本金或为1后则不再进行操作。
    **/

    var self = this,
        allMoney = self.data.money,
        //--总金额
        zs1 = allMoney / 2,
        //--总注数
        zhushu = self.zhushu,
        zs2 = zhushu.reduce(function (x, y) {
            return x + y;
        }, 0),
        //--实际注数
        diff = (zs1 - zs2).toFixed(0) * 1; //--最大递归次数，防死循环
    // var ms = self.ms.slice(0), mMaps = self.mMaps, cishu = 0;
    // var _ms = ms.sort((a, b) => a - b), step = diff / Math.abs(diff); //--加 或者减
    // diff: 差的注数 可能多几注也可能少几注
    console.log('diff', diff)
    if (diff>0){
        for (let i = 0; i < diff; i++) {
            self.list = getNewListByNum(self.list, [], 1); // 增加注数
        }
        self.dataTongbu();
    } else if (diff < 0){
        for (let i = 0; i < Math.abs(diff); i++) {
            const nArr = [], oArr = [];
            // 将需要减少的数组和无需操作的数组分隔开
            for (const item of self.list) {
                if (item.zhushu != 1) {
                    nArr.push(item)
                } else {
                    oArr.push(item)
                }
            }
            self.list = getNewListByNum(nArr, oArr, -1); // 减少注数
        }
        self.dataTongbu();
    }
    /*function todoAvg(diff) {
        //--找平，步骤2
        var doBreak = false; //--是否中止外循环
        for (var i = 0, len = _ms.length; i < len; i++) {
            var items = mMaps[_ms[i]];
            if (!doBreak && diff != 0 && items && Array.isArray(items)) {
                for (var m = 0, n = items.length; m < n; m++) {
                    // console.log(items[m].zhushu, items[m].zhushu + step, doBreak, diff);
                    if (items[m].zhushu + step <= 0) {
                        //--注数不足
                        doBreak = true; //--中止外循环
                        break;
                    }
                    diff -= step;
                    items[m].zhushu += step;
                    items[m].money = items[m].m * items[m].zhushu;
                    if (diff == 0) {
                        break;
                    }
                }
            } else if (doBreak || diff == 0) {
                break;
            }
        }
        if (diff != 0) {
            todoAvg(diff); //--递归找平
        }
    }
    todoAvg(diff); //--找平
    var _minArr = []; //--奖金小于本金的集合
    for (var i = 1, len = _ms.length; i < len; i++) {
        var items = mMaps[_ms[i]];
        for (var m = 0, n = items.length; m < n; m++) {
            if (items[m].money < allMoney) {
                _minArr.push(items[m]); //--获取奖金小于本金的的item
            }
        }
    }
    var min = _ms[0]; //--获取最小单注奖金
    var items = mMaps[min]; //--奖金最小的item数组
    var item = items[0];
    if (_minArr.length >= 1 && item.money - allMoney > 0) {
        //--步骤三，优化
        var yhNum = 0; //--可以提供的优化数量
        for (var i = 0, len = items.length; i < len; i++) {
            //--计算可以提供的优化数量
            var item = items[i];
            var x = parseInt((item.money - allMoney) / item.m);
            yhNum += x;
        }
        var _yhNum = yhNum;
        for (var i = 0, len = _minArr.length; i < len; i++) {
            //--计算小于本金的item，得出总计需要多少注用来优化
            var item = _minArr[i];
            var num = Math.floor((allMoney - item.money) / item.m) * 1 + 1;
            if (yhNum > num) {
                yhNum -= num;
                item.zhushu = item.zhushu * 1 + num;
            } else {
                item.zhushu = item.zhushu * 1 + yhNum;
                yhNum = 0;
            }
            item.money = item.zhushu * item.m;
        }
        var useNum = _yhNum - yhNum,
            avgNum = Math.floor(useNum / items.length),
            //--平均数
            modNum = useNum % items.length; //--余数
        for (var i = 0, len = items.length; i < len; i++) {
            //--将优化数平均到奖金最低的item里
            var item = items[i];
            item.zhushu -= avgNum;
            if (i + 1 <= modNum) {
                item.zhushu -= 1;
            }
            item.money = item.zhushu * item.m;
        }
    }
    var zs = [], moneys = [], maxMoneys = [];
    self.list.forEach(function (v, i) {
        zs.push(v.zhushu); //--注数集合
        moneys.push(v.money); //--各总奖金集合
    });
    self.zhushu = zs;
    self.moneys = moneys;
    self.maxMoneys = maxMoneys;*/
    /**
    xiuzheng(diff);
    function xiuzheng(diff){//--递归函数，修正平均优化所产生的差异
        cishu += 1;
        if(cishu > 500){//--超过最大递归次数，跳出
        self.dataTongbu();
        return;
        }
        var minMS = Math.min.apply(null, ms),//--最小单注金额
        items = mMaps[minMS.toFixed(2)];//console.log(minMS,items);
        // ms.splice(0, 1);
        var num = 0;
        for(var i = 0, len = items.length; i < len; i++){
        var z = items[i].zhushu;//console.log(z);
        if(diff < 0){
            diff += 1;//--差异修正
            items[i].zhushu = items[i].zhushu * 1 + 1;//--注数修正
        }else if(diff > 0){
            if(num < len){
            if(z > 1){
                diff -= 1;//--差异修正
                items[i].zhushu -= 1;//--注数修正
            }else if(z == 1){
                num += 1;//--不可修正数累加
                continue;//--跳出本次循环
            }
            }else{
            ms = Array.minus(ms, [minMS]);
            }
        }else if(diff == 0){
            self.dataTongbu();
            return;
        }
        }
        // console.log(num,len,diff,ms);
        if(num == len){ms = Array.minus(ms, [minMS]);}
        else if(len == 0){ms = Array.minus(ms, [minMS])}//--修正映射，移除空映射
        if(diff != 0 && ms.length > 0){
        xiuzheng(diff);//--递归执行
        }else{
        self.dataTongbu();
        }
    }
    */
};
optimize.prototype.doOrder = function (key) {
    //--排序
    var self = this,
        ms = self.ms.slice(0),
        //--单注金额集合
        mMaps = self.mMaps,
        //--单注金额映射
        allMoney = self.data.money,
        //--总金额
        ggMaps = self.ggMaps,
        num = 0; //--可优化注数
    self.listOrder = [];
    if (key == "hot" || key == "cold") {
        var minMS = key == "hot" ? Math.min.apply(null, ms) : Math.max.apply(null, ms),
            //--最小(大)单注金额
            items = mMaps[minMS.toFixed(2)],
            //--最小（大）金额对象集合
            ms = minus(ms, [minMS]); //--取差集，得出需要优化的数据
    }
    if (items) {
        for (var m = 0, n = items.length; m < n; m++) {
            var it = items[m];
            self.listOrder.push(it);
        }
    }
    ms.sort(function (a, b) {
        return a - b;
    });
    for (var x = 0, y = ggMaps.length; x < y; x++) {
        for (var i = 0, len = ms.length; i < len; i++) {
            var items = mMaps[ms[i]];
            // console.log(ms[i], items);
            // self.listOrder = self.listOrder.concat(items);
            for (var m = 0, n = items.length; m < n; m++) {
                var it = items[m];
                if (it.text.length == ggMaps[x]) {
                    self.listOrder.push(it);
                }
            }
        }
    }
    // console.log(self.listOrder);
    // console.log(ms);
};
optimize.prototype.doHot = function (key) {
    //--博热\博冷
    var self = this,
        ms = self.ms.slice(0),
        //--单注金额集合
        mMaps = self.mMaps,
        //--单注金额映射
        minMS = key == "hot" ? Math.min.apply(null, ms) : Math.max.apply(null, ms),
        //--最小(大)单注金额
        // minMS = minMS.toFixed(2),
        items = mMaps[minMS.toFixed(2)],
        //--最小（大）金额对象集合
        allMoney = self.data.money,
        //--总金额
        num = 0; //--可优化注数
    ms = minus(ms, [minMS]); //--取差集，得出需要优化的数据
    // console.log(ms, mMaps, minMS, items, allMoney);
    let usedNum = 0; // 已分配注数
    for (var i = 0, len = ms.length; i < len; i++) {
        var objs = mMaps[ms[i]];
        for (const it of objs){
            const x = Math.ceil(allMoney / it.m)
            it.hot = 0; //--更新博冷搏热标志
            it.zhushu = x;
            usedNum += x;
        }
    }
    if (items.length > 1) {
        const n = items.length;
        for (let i = 1; i < n; i++) {
            var it = items[i];
            const x = Math.ceil(allMoney / it.m)
            it.hot = 0; //--更新博冷搏热标志
            it.zhushu = x;
            usedNum += x;
        }
    }
    items[0].zhushu = (allMoney / 2) - usedNum; // 将剩余所有注数分配给第一个
    const { zhushu, m } = items[0]
    if ((zhushu * m) < allMoney){
        // 理论奖金小于用户输入的金额：说明博冷博热不成立，还是返回平均优化的数据
        self.doAvg()
    }else{
        items[0].hot = 1; //--更新博冷搏热标志
        self.dataTongbu();
        self.doOrder(key);
    }
};
optimize.prototype.doSubmit = function () {
    //--提交店铺
    var self = this;
    self.submitAction = "submit";
    self.doFangan();
};
optimize.prototype.doSave = function () {
    //--保存方案并执行跳转
    var self = this;
    self.submitAction = "save";
    self.doFangan();
};
optimize.prototype.doHemai = function () {
    var self = this;
    self.submitAction = 'hemai';
    self.doFangan();
};
optimize.prototype.doAdd = function (key, index) {
    //--增加或者减少注数
    var self = this,
        listInfo = self.listInfo,
        list = self.list,
        item = list.find(item => item.index === index);
    key = key || 1;
    if (item) {
        var m = item.m,
            zhushu = item.zhushu * 1,
            max = (100000 - listInfo.money) / 2 + zhushu; //--最大注数;
        zhushu += key;
        if (zhushu < 0) {
            zhushu = 0;
        } else if (zhushu > max) {
            zhushu = max;
        }
        item.zhushu = zhushu;
        item.money = m * zhushu;
        self.dataTongbu();
    }
};

export default optimize;
